#include <gtest/gtest.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "buffer.h"

namespace WebServerTest
{
    using namespace std;
    // 匿名空间，避免命名冲突
    class BufferTest : public testing::Test
    {
    protected:
        void SetUp() override
        {
            buffer_.RetrieveAll(); // 清空缓冲区
            file_data_ = "file write test";
        }

        Buffer buffer_;
        string file_data_;
    };

    TEST_F(BufferTest, InintState)
    {
        // 初始状态下的测试
        EXPECT_EQ(buffer_.ReadableBytes(), 0);    // 初始状态下，缓冲区为空
        EXPECT_EQ(buffer_.WritableBytes(), 1024); // 初始状态下，可写字节数为1024
        EXPECT_EQ(buffer_.PrependableBytes(), 0); // 初始状态下，头部预留字节数为0

        EXPECT_EQ(buffer_.BeginWrite(), buffer_.Peek()); // 初始状态下，开始写指针与Peek指针相同
    };

    TEST_F(BufferTest, AppendData)
    {
        // 添加数据

        const char *str = "Hello, World!";
        buffer_.Append(str, strlen(str)); // 添加字符串

        EXPECT_EQ(buffer_.ReadableBytes(), strlen(str));        // 可读字节数等于添加的字符串长度
        EXPECT_EQ(buffer_.WritableBytes(), 1024 - strlen(str)); // 可写字节数等于1024减去添加的字符串长度
        EXPECT_EQ(buffer_.PrependableBytes(), 0);               // 头部预留字节数为0
        EXPECT_EQ(0, strcmp(buffer_.Peek(), str));              // Peek指针指向添加的字符串开头

        buffer_.Append("1234567890", 10); // 添加10个字符

        EXPECT_EQ(buffer_.ReadableBytes(), strlen(str) + 10);        // 可读字节数等于添加的字符串长度加10
        EXPECT_EQ(buffer_.WritableBytes(), 1024 - strlen(str) - 10); // 可写字节数等于1024减去添加的字符串长度减去10
        EXPECT_EQ(buffer_.PrependableBytes(), 0);                    // 头部预留字节数为0
    }
    TEST_F(BufferTest,AppendDataOverflow){
        // 添加数据溢出
        Buffer small_buffer(10);
        const char *str = "aaaa aaaa aaaa";
        small_buffer.Append(str, strlen(str));
        EXPECT_EQ(small_buffer.ReadableBytes(), strlen(str));
        EXPECT_EQ(small_buffer.WritableBytes(), 1);

        string res_str=small_buffer.RetrieveAllToStr();
        EXPECT_STREQ(res_str.c_str(),str);

        int fd = open("append_data_overflow.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);  // 创建一个名为 output.txt 的文件
        if (fd < 0) {
            cerr << "Failed to open file for writing.";
        }
        string new_data="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        int ret = write(fd,new_data.c_str(),new_data.size());
        if(ret<0){
            cerr<<"Failed to write data to file."<<endl;
        }
        close(fd);  // 关闭文件描述符

        int fd_read = open("append_data_overflow.txt", O_RDONLY);
        int Errno = 0;
        small_buffer.ReadFd(fd_read,&Errno);
        if(Errno!=0){
            cerr<<"Failed to read data from file."<<endl;
        }
        close(fd_read);  // 关闭文件描述符

        EXPECT_STREQ(new_data.c_str(),small_buffer.Peek());
    }

    TEST_F(BufferTest, Retrive)
    {

        // 回退数据
        string str = "Hello, World!1234567890";
        buffer_.Append(str);
        EXPECT_EQ(buffer_.RetrieveAllToStr(), str);
        // 数据等于 初始状态下的测试
        EXPECT_EQ(buffer_.ReadableBytes(), 0);
        EXPECT_EQ(buffer_.WritableBytes(), 1024);
        EXPECT_EQ(buffer_.PrependableBytes(), 0);

        EXPECT_EQ(buffer_.BeginWrite(), buffer_.Peek());

        buffer_.Append(str);
        buffer_.Retrieve(5); // 回退5个字节

        EXPECT_EQ(buffer_.ReadableBytes(), str.size() - 5);    // 可读字节数等于添加的字符串长度减去5
        EXPECT_EQ(buffer_.WritableBytes(), 1024 - str.size()); // 可写字节数等于1024减去添加的字符串长度加5
        EXPECT_EQ(buffer_.PrependableBytes(), 5);              // 头部预留字节数为5
        EXPECT_EQ(0, strcmp(buffer_.Peek(), str.c_str() + 5)); // Peek指针指向回退后的字符串开头
    }

    TEST_F(BufferTest, Append)
    {
        // 添加数据
        const char *str = "Hello, World!";
        buffer_.Append(str, strlen(str)); // 添加字符串
        EXPECT_STREQ(str, buffer_.Peek());
        buffer_.RetrieveAll();

        string str2 = "1234567890";
        buffer_.Append(str2);
        EXPECT_STREQ(str2.c_str(), buffer_.Peek());
        buffer_.RetrieveAll();

        void *ptr=(void *)str;
        buffer_.Append(ptr, strlen(str));
        EXPECT_STREQ(str, buffer_.Peek());
        buffer_.RetrieveAll();
    }

        // 测试 WriteFd 函数
    TEST_F(BufferTest, WriteFdTest) {
        int fd = open("write_fd_test.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);  // 创建一个名为 output.txt 的文件
        if (fd < 0) {
            cerr<< "Failed to open file for writing.";
        }

        buffer_.Append(file_data_);  // 添加字符串
        int Errno = 0;
        ssize_t ret = buffer_.WriteFd(fd, &Errno);
        EXPECT_EQ(Errno, 0);
        EXPECT_GE(ret, file_data_.size());  
        close(fd);  // 关闭文件描述符

        //测试文件的内容是否正确
        int fd2 = open("write_fd_test.txt", O_RDONLY);
        char buffer[1024];
        ret = read(fd2, buffer, 1024);
        buffer[ret] = '\0';
        EXPECT_STREQ(file_data_.c_str(), buffer);
        close(fd2);  // 关闭文件描述符
    }

    TEST_F(BufferTest, ReadData){
        // 读取数据
        int fd2 = open("write_fd_test.txt", O_RDONLY);
        int Errno = 0;
        buffer_.ReadFd(fd2,&Errno);
        
        close(fd2);  // 关闭文件描述符
        EXPECT_STREQ(file_data_.c_str(), buffer_.Peek());
    }

};

